package com.jeesite.modules.dp.service.kccode;

import java.util.Date;
import java.util.List;

import com.jeesite.common.lang.StringUtils;
import com.jeesite.modules.enums.KcCodeStatusEnum;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.jeesite.common.entity.Page;
import com.jeesite.common.service.CrudService;
import com.jeesite.modules.dp.entity.kccode.DpKechengcode;
import com.jeesite.modules.dp.dao.kccode.DpKechengcodeDao;
import com.jeesite.common.service.ServiceException;
import com.jeesite.common.config.Global;
import com.jeesite.common.validator.ValidatorUtils;
import com.jeesite.common.utils.excel.ExcelImport;
import org.springframework.web.multipart.MultipartFile;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;

/**
 * 观看码管理Service
 *
 * @author hancing.com
 * @version 2025-01-02
 */
@Service
public class DpKechengcodeService extends CrudService<DpKechengcodeDao, DpKechengcode> {

    /**
     * 获取单条数据
     *
     * @param dpKechengcode
     * @return
     */
    @Override
    public DpKechengcode get(DpKechengcode dpKechengcode) {
        return super.get(dpKechengcode);
    }

    /**
     * 查询分页数据
     *
     * @param dpKechengcode 查询条件
     * @param dpKechengcode page 分页对象
     * @return
     */
    @Override
    public Page<DpKechengcode> findPage(DpKechengcode dpKechengcode) {
        return super.findPage(dpKechengcode);
    }

    /**
     * 查询列表数据
     *
     * @param dpKechengcode
     * @return
     */
    @Override
    public List<DpKechengcode> findList(DpKechengcode dpKechengcode) {
        return super.findList(dpKechengcode);
    }

    /**
     * 保存数据（插入或更新）
     *
     * @param dpKechengcode
     */
    @Override
    @Transactional
    public void save(DpKechengcode dpKechengcode) {
        super.save(dpKechengcode);

    }


    @Transactional
    public void saveBatch(List<DpKechengcode> list) {
        dao.insertBatch(list);

    }

    /**
     * 导入数据
     *
     * @param file 导入的数据文件
     */
    @Transactional
    public String importData(MultipartFile file) {
        if (file == null) {
            throw new ServiceException(text("请选择导入的数据文件！"));
        }
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();
        try (ExcelImport ei = new ExcelImport(file, 2, 0)) {
            List<DpKechengcode> list = ei.getDataList(DpKechengcode.class);
            for (DpKechengcode dpKechengcode : list) {
                try {
                    ValidatorUtils.validateWithException(dpKechengcode);
                    this.save(dpKechengcode);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、编号 " + dpKechengcode.getId() + " 导入成功");
                } catch (Exception e) {
                    failureNum++;
                    String msg = "<br/>" + failureNum + "、编号 " + dpKechengcode.getId() + " 导入失败：";
                    if (e instanceof ConstraintViolationException) {
                        ConstraintViolationException cve = (ConstraintViolationException) e;
                        for (ConstraintViolation<?> violation : cve.getConstraintViolations()) {
                            msg += Global.getText(violation.getMessage()) + " (" + violation.getPropertyPath() + ")";
                        }
                    } else {
                        msg += e.getMessage();
                    }
                    failureMsg.append(msg);
                    logger.error(msg, e);
                }
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            failureMsg.append(e.getMessage());
            return failureMsg.toString();
        }
        if (failureNum > 0) {
            failureMsg.insert(0, "很抱歉，导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            throw new ServiceException(failureMsg.toString());
        } else {
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
        }
        return successMsg.toString();
    }

    /**
     * 更新状态
     */
    @Override
    @Transactional
    public void updateStatus(DpKechengcode dpKechengcode) {
        super.updateStatus(dpKechengcode);
    }

    /**
     * 删除数据
     *
     * @param dpKechengcode
     */
    @Override
    @Transactional
    public void delete(DpKechengcode dpKechengcode) {
        super.delete(dpKechengcode);
    }

    @Transactional
    public DpKechengcode getLimit1Canuse(String kcid) {
        return dao.getLimit1Canuse(kcid);
    }

    @Transactional
    public void setOrderIdUsed(@Param("lockorderid") String lockorderid) {
        dao.setOrderIdUsed(lockorderid);
    }

    @Transactional
    public DpKechengcode findOrderCodes(@Param("lockorderid") String lockorderid) {
        List<DpKechengcode> list = dao.findOrderCodes(lockorderid);
        return (list == null || list.isEmpty()) ? null : list.getFirst();
    }

    public int findUnUsedKcCount(String kcid) {
        DpKechengcode dpKechengcode = new DpKechengcode();
        dpKechengcode.setKcid(kcid);
        dpKechengcode.setCodestatus(KcCodeStatusEnum.FREE.getCode());
        return (int) this.findCount(dpKechengcode);
    }

    /**
     * 课程码下单后会被锁定
     *
     * @param id          课程id
     * @param userNo      用户名
     * @param lockOrderId 订单id
     */
    public synchronized void lockKcCode(String id, String userNo, String lockOrderId) {
        DpKechengcode code = this.get(id);
        if (code != null) {
            code.setCodestatus(KcCodeStatusEnum.LOCKED.getCode());
            code.setLockorderid(lockOrderId);
            code.setLocktime(new Date(System.currentTimeMillis()));
            code.setUno(userNo);
            this.update(code);
        }
    }

    /**
     * 解锁，课程码下单后会被锁定，支付超时则取消订单，且解锁该课程码
     *
     * @param kcCodeId 课程code id
     */
    public void unLockKcCode(String kcCodeId) {
        if (!StringUtils.isBlank(kcCodeId)) {
            dao.unlockOrderUsed(kcCodeId);
        }
    }

    /**
     * 查询所有被锁定的课程码
     */
    public List<DpKechengcode> findLockedKcCodes() {
        return dao.findLockedCodes();
    }

}